#include "Task.hpp"
#include <string>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <cassert>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>

const int processnum=10;
std::vector<task_t> tasks;

class channel
{
public:
    channel(int cmdfd,int slaverid,const std::string &processname)
        :_cmdfd(cmdfd)
        ,_slaverid(slaverid)
        ,_processname(processname)
        {}

public:
    int _cmdfd;
    pid_t _slaverid;
    std::string _processname;
};

void slaver()
{
    // read(0)
    while(true)
    {
        int cmdcode = 0;
        int n=read(0,&cmdcode,sizeof(int));
        if(n == sizeof(int))
        {
            // 执行cmdcode对应任务
            std::cout << "slaver say@ get a command: " << getpid() << " : cmdcode: " << cmdcode << std::endl;
            if(n == 0)break;
        }
    }
}

void InitProcessPool(std::vector<channel>* channels)
{
    std::vector<int> oldfds;
    for(int i=0;i<processnum;i++)
    {
        int pipefd[2];
        int n=pipe(pipefd);
        assert(!n);
        (void)n;

        pid_t id=fork();
        // child
        if(id==0)
        {
            std::cout << "child: " << getpid() << " close history fd: ";
            for(auto fd : oldfds)
            {
                std::cout << fd << " ";
                close(fd);
            }
            std::cout << "\n";

            close(pipefd[1]);
            dup2(pipefd[0],0);
            close(pipefd[0]);
            slaver();
            std::cout << "process : " << getpid() << " quit" << std::endl;
            // slaver(pipefd[0]);
            exit(0);
        }
        // father
        close(pipefd[0]);
        
        std::string name="process-"+std::to_string(i);
        channels->push_back(channel(pipefd[1],id,name));
        oldfds.push_back(pipefd[1]);
    }
}

void Debug(const std::vector<channel> &channels)
{
    for(const auto &c:channels)
    {
        std::cout << c._cmdfd << " " << c._slaverid << " " << c._processname << std::endl;
    }
}

void Menu()
{
    std::cout << "###########################################" << std::endl;
    std::cout << "# 1. 刷新日志               2. 刷新野怪    #" <<std::endl;
    std::cout << "# 3. 检测软件               4. 刷新血量    #" <<std::endl;
    std::cout << "#                          0. 退出    #" <<std::endl;
    std::cout << "###########################################" << std::endl;
}

void ctrlSlaver(const std::vector<channel> &channels)
{
    int which=0;
    // int cnt = 5;
    while(true)
    {
        int select = 0;
        Menu();
        std::cout << "please Enter@ ";
        std::cin >> select;

        if(select <= 0 || select >= 5 )break;

        // 选择任务
        // int cmdcode = rand()%tasks.size();
        int cmdcode = select - 1;

        // 选择进程
        // int processpos = rand()%channels.size();

        std::cout << "father say: " << " cmdcode: " << cmdcode << "already sendto " << channels[which]._slaverid << " process name: " << channels[which]._processname << std::endl;

        // 发送任务
        write(channels[which]._cmdfd,&cmdcode,sizeof(cmdcode));

        which++;
        which %= channels.size();

        //cnt--;
        //sleep(1);
    }
}

void QuitProcess(const std::vector<channel> &channels)
{
    for(const auto &c:channels) close(c._cmdfd);
    for(const auto &c:channels) waitpid(c._slaverid,nullptr,0);
}

int main()
{
    LoadTask(&tasks);
    srand(time(nullptr)^getpid()^1023);
    std::vector<channel> channels;

    // 初始化
    InitProcessPool(&channels);
    // Debug(channels);

    // 控制子进程
    ctrlSlaver(channels);

    // 清理收尾
    QuitProcess(channels);
    return 0;
}